package com.chen.mkarm

import android.os.Bundle
import android.util.Log
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.statusBarsPadding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.AccountBox
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material.icons.filled.Home
import androidx.compose.material3.Button
import androidx.compose.material3.Card
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.material3.TextField
import androidx.compose.material3.adaptive.navigationsuite.NavigationSuiteScaffold
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.chen.mkarm.ui.theme.MkarmTheme
import com.hivemq.client.mqtt.MqttGlobalPublishFilter
import com.hivemq.client.mqtt.datatypes.MqttQos
import com.hivemq.client.mqtt.mqtt5.Mqtt5AsyncClient
import com.hivemq.client.mqtt.mqtt5.Mqtt5Client
import com.hivemq.client.mqtt.mqtt5.message.connect.connack.Mqtt5ConnAck
import com.hivemq.client.mqtt.mqtt5.message.publish.Mqtt5Publish
import com.hivemq.client.mqtt.mqtt5.message.subscribe.suback.Mqtt5SubAck
import com.hoho.android.usbserial.driver.UsbSerialPort
import java.nio.charset.CharsetEncoder
import java.util.UUID
import java.util.concurrent.CountDownLatch
import java.util.function.BiConsumer
import java.util.function.Consumer
import java.nio.charset.StandardCharsets

class MainActivity : ComponentActivity() {
    // 创建一个可观察的状态变量
    private var logs by mutableStateOf(listOf("串口消息历史"))
    // 创建MQTT消息历史记录的状态变量
    private var mqttMessages by mutableStateOf(listOf("MQTT消息历史"))
    
    private var MyUSB : UsbSerialManager? = null

    val client: Mqtt5AsyncClient = Mqtt5Client.builder()
        .serverHost("broker.emqx.io")
        .automaticReconnectWithDefaultConfig()
        .buildAsync()

    val serverUri: String = "tcp://broker.emqx.io:1883"
    var clientId: String = UUID.randomUUID().toString()
    val subscriptionTopic: String = "mkarm/speed"
    val publishTopic: String = "mkarm/speed"

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        initSerialPort()
        setContent {
            MkarmTheme {
                MkarmApp(logs, mqttMessages, ::sendData, ::publishMessage)
            }
        }
        connect()
    }

    //退出页面时候注销
    override fun onDestroy() {
        super.onDestroy()
        MyUSB?.closeDevice()
    }

    /////////////////////////////////////////////////////////
    //以下是MQTT调用方法
    companion object {
        const val TAG = "AndroidMqttClient"
    }

    fun connect(){
        // 使用 CountDownLatch 保持程序运行以持续接收消息
        val latch : CountDownLatch = CountDownLatch(1)

        //2.设置接收消息的回调
        client.toAsync().publishes(MqttGlobalPublishFilter.ALL, Consumer { publish: Mqtt5Publish? ->
            val topic = publish?.topic ?: "null"
            val messageContent = if (publish?.payloadAsBytes != null) {
                String(publish.payloadAsBytes, StandardCharsets.UTF_8)
            } else {
                "null"
            }
            addToHistory("$topic: $messageContent")
        })

        //3.连接到 MQTT 服务器
        client.connect()
            .whenComplete(BiConsumer { connAck: Mqtt5ConnAck?, throwable: Throwable? ->
                if (throwable != null) {
                    Log.e(TAG, "❌ 连接失败: " + throwable.message)
                } else {
                    Log.i(TAG,"✅ 成功连接到 MQTT 服务器: " + serverUri)

                    // 4. 订阅主题
                    client.subscribeWith()
                        .topicFilter(subscriptionTopic)
                        .qos(MqttQos.AT_LEAST_ONCE) // QoS 1
                        .send()
                        .whenComplete(BiConsumer { subAck: Mqtt5SubAck?, subThrowable: Throwable? ->
                            if (subThrowable != null) {
                                System.err.println("❌ 订阅失败: " + subThrowable.message)
                            } else {
                                Log.i(TAG,"📬 成功订阅主题: " + subscriptionTopic)
                                Log.i(TAG,"⏳ 等待接收消息...")
                            }
                        })
                }
            })

        // 5. 添加关闭钩子，优雅断开连接
        Runtime.getRuntime().addShutdownHook(Thread(Runnable {
            println("\n🛑 正在断开连接...")
            client.disconnect()
            println("👋 程序已退出")
        }))

        //保持线程运行
        //latch.await()
    }

    fun publishMessage(publishMsg : String){
        client.publishWith()
            .topic(publishTopic)
            .qos(MqttQos.AT_LEAST_ONCE)
            .payload(publishMsg.toByteArray())
            .send()
        Log.i(TAG, "published: we do not receive our own messages");
    }

    private fun addToHistory(mainText: String?) {
        Log.i(TAG, "$mainText")
        // 更新MQTT消息历史记录
        if (mainText != null) {
            val updatedMessages = mqttMessages + listOf(mainText)
            // 限制历史记录长度，避免内存占用过大
            if (updatedMessages.size > 50) {
                mqttMessages = updatedMessages.drop(1)
            } else {
                mqttMessages = updatedMessages
            }
        }
    }

    /////////////////////////////////////////////////////////
    //以下是串口调用方法
    fun initSerialPort() {
        val param: UsbSerialParams = UsbSerialParams(9600, 8, 1, UsbSerialPort.PARITY_NONE, true)
        MyUSB = UsbSerialManager(this, param, ::addNewLog)

        MyUSB?.requestPermission()
        if (MyUSB?.hasPermission() == false) {
            println("没有打开权限")
        }

        MyUSB?.openDevice()
    }

    // 在这里更新logs变量,则对应的Composer就会更新显示
    public fun addNewLog(newLog: String) {
        val updatedLogs = logs + listOf(newLog)
        logs = updatedLogs
    }

    //作为回调函数传给Composer
    public fun sendData(data:String){
        MyUSB?.sendData(data)
    }
}

//@PreviewScreenSizes
@Composable
fun MkarmApp(logs: List<String>, mqttMessages: List<String>, senddata: (String) -> Unit, publish:(String)->Unit) {
    var currentDestination by rememberSaveable { mutableStateOf(AppDestinations.HOME) }

    NavigationSuiteScaffold(
        navigationSuiteItems = {
            AppDestinations.entries.forEach {
                item(
                    icon = {
                        Icon(
                            it.icon,
                            contentDescription = it.label
                        )
                    },
                    label = { Text(it.label) },
                    selected = it == currentDestination,
                    onClick = { currentDestination = it }
                )
            }
        }
    ) {
        Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
            Column(modifier = Modifier.fillMaxSize()) {
                MaterialTitleBar("麦克阿姆机器人", currentDestination.label);

                // 根据当前选中的目标显示不同的页面内容
                when (currentDestination) {
                    AppDestinations.HOME -> HomeScreen(publish, mqttMessages, modifier = Modifier.padding(innerPadding))
                    AppDestinations.FAVORITES -> SerialPortScreen(logs, senddata, modifier = Modifier.padding(innerPadding))
                    AppDestinations.PROFILE -> ConfigurationScreen(modifier = Modifier.padding(innerPadding))
                }
            }
        }
    }
}
enum class AppDestinations(
    val label: String,
    val icon: ImageVector,
) {
    HOME("首页", Icons.Default.Home),
    FAVORITES("串口", Icons.Default.Favorite),
    PROFILE("配置", Icons.Default.AccountBox),
}

//实现TOPBAR标题栏
@Composable
fun MaterialTitleBar(
    title: String,
    subtitle: String? = null,
) {
    Surface(
        color = MaterialTheme.colorScheme.primary,
        shadowElevation = 6.dp
    ) {
        Row(
            Modifier
                .padding(16.dp)
                .statusBarsPadding(),
            horizontalArrangement = Arrangement.SpaceBetween,
            verticalAlignment = Alignment.CenterVertically
        ) {
            Column(Modifier.weight(1f)) {
                Text(title, style = MaterialTheme.typography.titleLarge)
                subtitle?.let {
                    Text(it, style = MaterialTheme.typography.bodySmall)
                }
            }
        }
    }
}

/////////////////////////////////////////////////////////////////////////////////
//----------------------------首页组件--------------------------------------------
// 首页内容组件
@Composable
fun HomeScreen(publish : (String)->Unit, mqttMessages: List<String>, modifier: Modifier = Modifier) {
    Column(modifier = modifier.padding(16.dp)) {
        // 这里可以添加更多首页的UI元素
        ShadowedBoxSendMqtt(publish)
        MqttMessageScrollList(mqttMessages)
        CarStatusList("50km/h","80%","经度：123.456")
    }
}
@Composable
fun ShadowedBoxSendMqtt(publish : (String)->Unit) {
    Card(modifier = Modifier
        .height(150.dp)
        .fillMaxSize()
        .padding(4.dp)) {
        Box(
            contentAlignment = Alignment.Center,
            modifier = Modifier.padding(16.dp)
        ) {
            Column {
                // 用于存储新输入项的状态变量
                var newItem by remember { mutableStateOf("") }

                // 提供一个文本输入框让用户输入新项
                TextField(value = newItem, onValueChange = { newItem = it }, label = { Text("Enter new item") })
                // 提供一个按钮来添加新项到列表中
                Button(onClick = {
                    if (newItem.isNotBlank()) {
                        //发送串口数据到机器人
                        println("发送串口数据到机器人：$newItem")
                        publish(newItem)
                        newItem = "" // 清空输入框
                    }
                }) {
                    Text("发送")
                }
            }
        }
    }
}

@Composable
fun MqttMessageScrollList(items: List<String>) {
    LazyColumn(modifier = Modifier
        .height(400.dp)
        .fillMaxWidth()
        .background(color = Color.Green)) {
        // 使用items扩展函数来遍历和渲染列表中的每一项
        items(items) { item ->
            Text(
                text = item,
                style = androidx.compose.ui.text.TextStyle(textAlign = TextAlign.Start)
            )
        }
    }
}

//显示一个列表，显示当前小车的状态,包含当前速度、当前电量、当前定位信息等
//每一行包含标题和值，标题靠左，值靠右
@Composable
fun CarStatusList(speed: String, battery: String, location: String) {
    Card(modifier = Modifier.padding(16.dp)) {
        Column(modifier = Modifier.padding(16.dp)) {
            Text("当前状态", style = MaterialTheme.typography.bodyLarge, modifier = Modifier.background(color = Color.Red) )// 标题头
            Spacer(modifier = Modifier.height(16.dp))
            var title = arrayOf("当前速度", "当前电量", "定位信息")
            var value = arrayOf(23, 44, 522)

            for (i in 0..2) {
                Row(
                    modifier = Modifier.fillMaxWidth(),
                    horizontalArrangement = Arrangement.SpaceBetween
                ) {
                    Text(title[i])
                    Text(value[i].toString(), fontWeight = FontWeight.Bold)
                }
                HorizontalDivider(
                    color = MaterialTheme.colorScheme.onSurface,
                    thickness = 1.dp
                ) // 添加横线
                Spacer(modifier = Modifier.height(8.dp))
            }
        }
    }
}

/////////////////////////////////////////////////////////////////////////////////
//----------------------------配置页组件--------------------------------------------
@Composable
fun ConfigurationScreen(modifier: Modifier = Modifier) {
    Column(modifier = modifier.padding(16.dp)) {
        Text(text = "应用配置", style = MaterialTheme.typography.headlineMedium)
        Spacer(modifier = Modifier.height(16.dp))
        Text(text = "这是配置页面内容区域", style = MaterialTheme.typography.bodySmall)
        // 这里可以添加更多配置页面的UI元素
    }
}

@Composable
fun Greeting(name: String, modifier: Modifier = Modifier) {
    Text(
        text = "Hello $name!",
        modifier = modifier
    )
}

@Preview(showBackground = true)
@Composable
fun GreetingPreview() {
    MkarmTheme {
        Greeting("Android")
    }
}